#pragma once

#include "rpc/RPCSession.h"

class GameSessionHandler;

class GameSession : public RPCSession,
	public enable_linked_from_this<GameSession>
{
public:
	GameSession();
	virtual ~GameSession();

	virtual int HandlePacket(INetPacket *pck);
	virtual void OnShutdownSession();

	static void Feedback(const std::weak_ptr<GameSession>& gsPtr,
		const INetStream& data, uint64 sn, int32 err = RPCErrorNone,
		bool eof = true);
	static void FeedbackError(const std::weak_ptr<GameSession>& gsPtr,
		uint64 sn, int32 err);

private:
	friend GameSessionHandler;
	bool m_isReady;
};

#define GSRPCAsyncTaskArgs \
	pckPtr = std::shared_ptr<INetPacket>(&pck), \
	gsPtr = pSession->linked_from_this(), \
	info
#define GSAsyncTaskArgs \
	pckPtr = std::shared_ptr<INetPacket>(&pck)

#define AutoFeedbackPrivate(buffer, error) \
	DBPError error = DBPErrorNone; \
	_defer_r( \
		if (error != DBPErrorNone) { \
			GameSession::FeedbackError(gsPtr, info.sn, error); \
		} else { \
			GameSession::Feedback(gsPtr, buffer, info.sn); \
		} \
	)
#define AutoFeedbackLarge(buffer, error) \
	TNetBuffer<65536> buffer; \
	AutoFeedbackPrivate(buffer, error)
#define AutoFeedback(buffer, error) \
	NetBuffer buffer; \
	AutoFeedbackPrivate(buffer, error)

#define AutoTransaction_FailReturn(connPtr, error) \
	if (!connPtr->Begin()) { \
		error = DBPErrorBeginMysqlFailed; \
		return; \
	} \
	_defer_r( \
		if (error == DBPErrorNone) { \
			if (!connPtr->Commit()) { \
				error = DBPErrorCommitMysqlFailed; \
			} \
		} else { \
			if (!connPtr->Rollback()) { \
				WLOG("Rollback failed."); \
			} \
		} \
	)
